package cn.jasonone.hm.netdisc.controller;

import cn.jasonone.hm.netdisc.model.dto.HttpResult;
import cn.jasonone.hm.netdisc.service.CurdService;
import cn.jasonone.hm.netdisc.util.DTOUtil;
import cn.jasonone.hm.netdisc.util.ErrorUtil;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基本CURD操作控制器接口
 * @author Jason
 * @date 2020-07-20 12:30:07
 */
@Slf4j
public abstract class CurdController<T,DTO extends T,IDTO extends T,ID> {
	/**
	 * 返回当前的模块名(视图所存放的文件夹名称)
	 * @return 模块名
	 */
	public abstract String getModelName();
	
	/**
	 * 获取当前模块的基础CURD业务对象
	 * @return 业务对象实例
	 */
	public abstract CurdService<T,ID> getCurdService();
	
	public abstract Class<?> getVoType();
	
	// 主页
	@GetMapping
	public String home(){
		return getModelName()+"/index";
	}
	// 查询
	@GetMapping(path="/search",produces = MediaType.TEXT_HTML_VALUE)
	public String query(DTO t, Model model){
		List<T> list = getCurdService().findAll(t);
		model.addAttribute("items", DTOUtil.toVo(list, getVoType()));
		return getModelName()+"/searchResult";
	}
	// 查询: ID
	@GetMapping("/search")
	@ResponseBody
	public HttpResult query(DTO t,
	                        @RequestParam(defaultValue = "0")int page,
	                        @RequestParam(defaultValue = "10")int limit
	                    ){
		PageInfo pageInfo = getCurdService().findAll(t, page, limit);
		pageInfo.setList(DTOUtil.toVo(pageInfo.getList(), getVoType()));
		return HttpResult.success("查询成功", pageInfo);
	}
	// 保存:
	@GetMapping({"/edit","/edit/{id}"})
	public String edit(@PathVariable ID id,Model model){
		T t = this.getCurdService().findById(id);
		model.addAttribute("entity", t);
		return getModelName()+"/edit";
	}
	@PutMapping("/add")
	@ResponseBody
	public HttpResult add(@Valid IDTO t, BindingResult br){
		if(br.hasErrors()){
			List<FieldError> errors = br.getFieldErrors();
			HttpResult result = HttpResult.create(400, "非法的参数");
			Map<String,Map<String,Object>> objects = new HashMap<>();
			
			for (FieldError error : errors) {
				Map<String,Object> msg=new HashMap<>();
				String field = error.getField();
				String objectName = error.getObjectName();
				Object value = error.getRejectedValue();
				String message = error.getDefaultMessage();
				if(!objects.containsKey(objectName)){
					objects.put(objectName,new HashMap<>());
				}
				msg.put("value", value);
				msg.put("message", message);
				objects.get(objectName).put(field,msg);
			}
			result.addAttribute("errors", objects);
			return result;
		}
		try {
			this.getCurdService().save((T)t);
			return HttpResult.success("保存成功");
		}catch (Exception e){
			log.error("保存失败", e);
			return HttpResult.create(500, "保存失败").addAttribute("errorMsg", e.toString());
		}
	}
	@PostMapping("/update")
	@ResponseBody
	public HttpResult update(@Valid DTO t, BindingResult br){
		if(br.hasErrors()){
			return HttpResult.create(400, "非法的参数").addAttribute("errors", ErrorUtil.parseErrors(br));
		}
		try {
			this.getCurdService().save((T)t);
			return HttpResult.success("保存成功");
		}catch (Exception e){
			log.error("保存失败", e);
			return HttpResult.create(500, "保存失败").addAttribute("errorMsg", e.toString());
		}
	}
	// 批量删除: ID
	@DeleteMapping
	@ResponseBody
	public HttpResult delete(@RequestParam("id") Integer [] ids,@RequestParam(defaultValue = "false")Boolean logical){
		try {
			this.getCurdService().deleteByIds(logical, ids);
			return HttpResult.success("删除成功");
		}catch (Exception e){
			log.error("删除失败", e);
			return HttpResult.create(500, "删除失败").addAttribute("errorMsg", e.toString());
		}
	}
}
